from django.contrib.admin.widgets import AutocompleteSelect
from django.contrib.admin import widgets
from django.contrib.admin.options import get_ul_class
from django.utils.translation import gettext as _
from django.contrib.admin.widgets import (
    AutocompleteSelect, AutocompleteSelectMultiple,
)
from django.forms.widgets import CheckboxSelectMultiple, SelectMultiple
from django.utils.text import format_lazy

from apps.user.models import Firm
from django.contrib.gis import admin
from django import forms

def get_firm_queryset(request, qs, model):
        if request.user.global_user:
            return qs
        if hasattr(model, 'firm_id'):
            if request.user.firm_id is None:
                if model._meta.label == 'user.User':
                    qs = qs.filter(id=request.user.id)
                else:
                    qs = qs.none()
            else:
                qs = qs.filter(firm_id=request.user.firm_id)
        return qs


class BaseModelForm(forms.ModelForm):
    def save(self, commit=True):
        if self.request is not None and not self.request.user.global_user and hasattr(self.instance, 'firm_id'):
            self.instance.firm_id = self.request.user.firm_id
        return super().save(commit)

    def get_initial_for_field(self, field, field_name):
        """
        Return initial data for field on form. Use initial data from the form
        or the field, in that order. Evaluate callable values.
        """
        if not getattr(self, 'change_mode', True):
            if hasattr(field, 'geom_type') and field.geom_type == 'POINT':
                if getattr(self, 'request', None) and getattr(self.request, 'user', None) and getattr(self.request.user, 'default_point', None) :
                    return self.request.user.default_point
            if hasattr(field, 'geom_type') and field.geom_type == 'POLYGON':
                if getattr(self, 'request', None) and getattr(self.request, 'user', None) and getattr(self.request.user, 'default_polygon', None) :
                    return self.request.user.default_polygon
            if hasattr(field, 'geom_type') and field.geom_type == 'LINESTRING':
                if getattr(self, 'request', None) and getattr(self.request, 'user', None) and getattr(self.request.user, 'default_linestring', None) :
                    return self.request.user.default_linestring
        return super().get_initial_for_field(field, field_name)

class BaseGisAdmin(admin.OSMGeoAdmin):
    openlayers_url = 'plugins/openlayers-2.13.1/lib/OpenLayers.js'
    map_template = 'gis/admin/mopenlayers.html'
    num_zoom = 19
    max_zoom = 19
    map_width = 800
    map_height = 600
    wms_url = [
        'http://rt0.map.gtimg.com/realtimerender?',
        'http://rt1.map.gtimg.com/realtimerender?',
        'http://rt2.map.gtimg.com/realtimerender?',
        'http://rt3.map.gtimg.com/realtimerender?'
    ]
    form = BaseModelForm

    def get_queryset(self, request):
        qs = super().get_queryset(request)
        return get_firm_queryset(request, qs, self.model)
    
    def get_exclude(self, request, obj=None):
        """
        Hook for specifying exclude.
        """
        exclude = []
        if not request.user.global_user:
            exclude = ['firm', 'global_user', 'expire_time', 'is_active', 'groups', 'user_permissions']
        if self.exclude:
            exclude.extend(self.exclude)
        return exclude

    def get_form(self, request, obj=None, change=False, **kwargs):
        form =  super().get_form(request, obj, change, **kwargs)
        form.request = request
        form.change_mode = change
        return form
        
    def save_form(self, request, form, change):
        form.request = request
        return super().save_form(request, form, change)
    
    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        """
        Get a form Field for a ForeignKey.
        """
        db = kwargs.get('using')

        if 'widget' not in kwargs:
            if db_field.name in self.get_autocomplete_fields(request):
                kwargs['widget'] = AutocompleteSelect(db_field.remote_field, self.admin_site, using=db)
            elif db_field.name in self.raw_id_fields:
                kwargs['widget'] = widgets.ForeignKeyRawIdWidget(db_field.remote_field, self.admin_site, using=db)
            elif db_field.name in self.radio_fields:
                kwargs['widget'] = widgets.AdminRadioSelect(attrs={
                    'class': get_ul_class(self.radio_fields[db_field.name]),
                })
                kwargs['empty_label'] = _('None') if db_field.blank else None

        if 'queryset' not in kwargs:
            queryset = self.get_field_queryset(db, db_field, request)
            if queryset is not None:
                kwargs['queryset'] = queryset
        db_field.request = request
        return db_field.formfield(**kwargs)

    def formfield_for_manytomany(self, db_field, request, **kwargs):
        """
        Get a form Field for a ManyToManyField.
        """
        # If it uses an intermediary model that isn't auto created, don't show
        # a field in admin.
        if not db_field.remote_field.through._meta.auto_created:
            return None
        db = kwargs.get('using')

        if 'widget' not in kwargs:
            autocomplete_fields = self.get_autocomplete_fields(request)
            if db_field.name in autocomplete_fields:
                kwargs['widget'] = AutocompleteSelectMultiple(
                    db_field.remote_field,
                    self.admin_site,
                    using=db,
                )
            elif db_field.name in self.raw_id_fields:
                kwargs['widget'] = widgets.ManyToManyRawIdWidget(
                    db_field.remote_field,
                    self.admin_site,
                    using=db,
                )
            elif db_field.name in [*self.filter_vertical, *self.filter_horizontal]:
                kwargs['widget'] = widgets.FilteredSelectMultiple(
                    db_field.verbose_name,
                    db_field.name in self.filter_vertical
                )
        if 'queryset' not in kwargs:
            queryset = self.get_field_queryset(db, db_field, request)
            if queryset is not None:
                kwargs['queryset'] = queryset

        db_field.request = request
        form_field = db_field.formfield(**kwargs)
        if (isinstance(form_field.widget, SelectMultiple) and
                not isinstance(form_field.widget, (CheckboxSelectMultiple, AutocompleteSelectMultiple))):
            msg = _('Hold down “Control”, or “Command” on a Mac, to select more than one.')
            help_text = form_field.help_text
            form_field.help_text = format_lazy('{} {}', help_text, msg) if help_text else msg
        return form_field

class BaseTabularInline(admin.TabularInline):     
    def get_exclude(self, request, obj=None):
        """
        Hook for specifying exclude.
        """
        exclude = []
        if not request.user.global_user:
            exclude = ['firm', 'global_user', 'expire_time', 'is_active', 'groups', 'user_permissions']
        if self.exclude:
            exclude.extend(self.exclude)
        return exclude

    def get_form(self, request, obj=None, change=False, **kwargs):
        form =  super().get_form(request, obj, change, **kwargs)
        form.request = request
        form.change_mode = change
        return form
    
    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        """
        Get a form Field for a ForeignKey.
        """
        db = kwargs.get('using')

        if 'widget' not in kwargs:
            if db_field.name in self.get_autocomplete_fields(request):
                kwargs['widget'] = AutocompleteSelect(db_field.remote_field, self.admin_site, using=db)
            elif db_field.name in self.raw_id_fields:
                kwargs['widget'] = widgets.ForeignKeyRawIdWidget(db_field.remote_field, self.admin_site, using=db)
            elif db_field.name in self.radio_fields:
                kwargs['widget'] = widgets.AdminRadioSelect(attrs={
                    'class': get_ul_class(self.radio_fields[db_field.name]),
                })
                kwargs['empty_label'] = _('None') if db_field.blank else None

        if 'queryset' not in kwargs:
            queryset = self.get_field_queryset(db, db_field, request)
            if queryset is not None:
                kwargs['queryset'] = queryset
        db_field.request = request
        return db_field.formfield(**kwargs)
